package com.itheima.ui;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

/**
 * @author zhangbaiyan
 * @date 2024-08-08 10:12
 * @description:
 * @version:
 */
public class GameJFrame extends JFrame  implements KeyListener, ActionListener {
    //JFrame 界面,窗体
    //子类呢?也表述界面,窗体
    //规定:GameJFrame这个界面表示就是游戏的主界面
    //以后跟游戏相关的所有逻辑都写在这个类中

 //创建一个二维数组
 //目的:用来管理数据
 //加载图片的时候,会根据二维数组中的数据进行加载
 int[][] data=new int[4][4];

 //记录空白方块再二维数组中的位置
 int x = 0;
 int y = 0;

 //定义一个变量,记录当前展示图片的路径
 String path="image\\animal\\animal3\\";

 //定义一个二维数组,存储正确的数据
 int[][] win={
  {1,2,3,4},
  {5,6,7,8},
  {9,10,11,12},
  {13,14,15,0}
 };

 //定义变量用来统计步数
 int step = 0;

 //创建选项下面的条目对象
 JMenuItem replayItem = new JMenuItem("重新游戏");
 JMenuItem reLoginItem = new JMenuItem("重新登录");
 JMenuItem closeItem = new JMenuItem("关闭游戏");

 JMenuItem accountItem=new JMenuItem("公众号");

 public GameJFrame() {
     //初始化界面
     initJFrame();

     //初始化菜单
     initJMenuBar();

     //初始化数据(打乱)
     initData();

     //初始化图片
     initImage();

     //让界面显示出来,建议写道最后
     setVisible(true);

     //给整个界面添加键盘监听事件
     this.addKeyListener(this);
    }

    //初始化数据(打乱)
 private void initData() {
  //1.定义一个一维数组
  int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
  //打乱数组的数据顺序
  //遍历数组,得到每一个元素,拿着每一个元素跟随机索引上的数据进行交换
  Random random = new Random();
  for (int i = 0; i < tempArr.length; i++) {
   //获取随机索引
   int index = random.nextInt(tempArr.length);
   //拿着遍历到的每一个数据,跟随机索引上的数据进行交换
   int temp = tempArr[i];
   tempArr[i] = tempArr[index];
   tempArr[index] = temp;

  }

  System.out.println();


  //5.给二维数组添加数据

  //解法二:
  //遍历二维数组,给里面的每一个数据赋值
  int index=0;
  for (int i = 0; i < data.length; i++) {
   for (int j = 0; j < data.length; j++) {
    if (tempArr[index]==0){
     x=i;
     y=j;
    }
    data[i][j]=tempArr[index];
    index++;
   }
  }



 }

 //初始化图片
 //添加图片的时候,就需要按照二维数组中管理的数据添加图片
 private void initImage() {
  //清空原本已经出现的所有图片
  this.getContentPane().removeAll();

  if (victory()){
   //显示胜利的图标
   JLabel winJLabel=new JLabel(new ImageIcon("C:\\Users\\17685\\Desktop\\rouyi-906\\xuexi\\image\\win.png"));
   winJLabel.setBounds(203,283,197,73);
   this.getContentPane().add(winJLabel);

  }

  JLabel steptCount=new JLabel("步数:"+step);
  steptCount.setBounds(50,30,100,20);
  this.getContentPane().add(steptCount);

     //路径分为两种
     //绝对路径:一定是从盘符开始的。C:\  D:\
     //相对路径:不是从盘符开始的
     //相对路径相对当前项目而言的。 aaa\\bbb
     //再当前项目下,去找aaa文件夹,里面再找bbb文件夹

     //细节:
     //先加载的图片再上方,后加载的图片塞再下面

     //外循环 --- 把内循环重复了4次
  for (int i = 0; i <4 ; i++) {
   //内内循环 --- 表示在一行添加4张图片
   for (int j = 0; j < 4; j++) {
    //获取当前要加载图片的序号
    int number = data[i][j];
    //创建一个图片ImageIcon的对象
    ImageIcon icon1=new ImageIcon(path+number+".jpg");
    //创建一个JLabel的对象(管理容器)
    JLabel jLabel = new JLabel(icon1);
    //指定图片位置
    jLabel.setBounds(105*j+83,105*i+134,105,105);
    //图片添加边框
    //0:表示让图片凸起来
    //1:表示让图片凹下去
    jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
    //把管理容器添加到界面中
//     this.add(jLabel);
    //先获取界面中的隐藏容器
    this.getContentPane().add(jLabel);


   }



  }


  //添加背景图片
  JLabel background =new JLabel(new ImageIcon("image\\background.png"));
  background.setBounds(40,40,508,560);
  //把背景图片添加到界面中
  this.getContentPane().add(background);

  //刷新一下界面
  this.getContentPane().repaint();
 }


//初始化菜单
 private void initJMenuBar() {
  //创建整个的菜单对象
  JMenuBar jMenuBar = new JMenuBar();

  //创选菜单上面的两个选项的对象(功能 关于我们)
  JMenu functionjMenu = new JMenu("功能");
  JMenu aboutjMenu = new JMenu("关于我们");


  //将每一个选项下面的条目添加到选项当中
  functionjMenu.add(replayItem);
  functionjMenu.add(reLoginItem);
  functionjMenu.add(closeItem);

  aboutjMenu.add(accountItem);

  //给条目绑定事件
  replayItem.addActionListener(this);
  reLoginItem.addActionListener(this);
  closeItem.addActionListener(this);
  accountItem.addActionListener(this);

  //将菜单里面的两个选项添加到菜单当中
  jMenuBar.add(functionjMenu);
  jMenuBar.add(aboutjMenu);

  //给整个界面设置菜单
  this.setJMenuBar(jMenuBar);
 }

 //初始化界面
 private void initJFrame() {
  //设置界面的宽高
  setSize(603, 680);
  //设置界面的标题
  setTitle("拼图单机版V1.0");
  //设置界面置顶
  setAlwaysOnTop(true);
  //设置界面居中
  setLocationRelativeTo(null);
  //设置关闭模式
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
//  setDefaultCloseOperation(3);

  //取消默认的居中放置,只有取消了才会按照xy轴的形式添加组件
  this.setLayout(null);
 }

 @Override
 public void keyTyped(KeyEvent e) {

 }

 @Override
 public void keyPressed(KeyEvent e) {
  int code=e.getKeyCode();
  if (code==65){
    //把界面中所有的图片全部删除
   this.getContentPane().removeAll();
   //加载第一张完整的图片
   JLabel all = new JLabel(new ImageIcon(path+"all.jpg"));
   all.setBounds(83,134,420,420);
   this.getContentPane().add(all);
   //加载背景图片
   //添加背景图片
   JLabel background =new JLabel(new ImageIcon("image\\background.png"));
   background.setBounds(40,40,508,560);
   //把背景图片添加到界面中
   this.getContentPane().add(background);

   //刷新一下界面
   this.getContentPane().repaint();


  }
 }

 @Override
 public void keyReleased(KeyEvent e) {
  //判断游戏是否胜利,如果胜利,此方法直接结束,不能再执行下面的移动代码了
  if(victory()){
   //结束方法
   return;
  }

  //对上下左右进行判断
  //左:37 上:38 右:39 下:40
  int code = e.getKeyCode();
//  System.out.println(code);
  if (code==37){
   System.out.println("向左");
   if (y==3){
    //表示空白方块已经再最左方了.到达最左方没有图片再能移动了
    return;
   }
   //逻辑:
   //把空白方块右侧的数字往左移动
   data[x][y]=data[x][y+1];
   data[x][y+1]=0;
   y++;

   //每移动一次,计数器就自增一次.
   step++;

   //调用方法按照最新的数字加图片
   initImage();
 }else if (code==38){
   System.out.println("向上");
   if (x==3){
    //表示空白方块已经再最下方了.达的下面没有图片再能移动了
    return;
   }
   //逻辑
   //把空白方块下方的数字往上移动
   //x,y 表示空白方块
   //x+1,y表示空白下方的数字

   //把空白下方的数字赋值给空白方块
   data[x][y]=data[x+1][y];
   data[x+1][y]=0;
   x++;

   //每移动一次,计数器就自增一次.
   step++;

   //掉用方法按照最新的数字加载图片
   initImage();
  }else if (code == 39){
   System.out.println("向右");
   if (y==0){
    //表示空白方块已经再最右方了.到达最右方没有图片再能移动了
    return;
   }
   //逻辑:
   //把空白方块左侧的数字往右移动
   data[x][y]=data[x][y-1];
   data[x][y-1]=0;
   y--;

   //每移动一次,计数器就自增一次.
   step++;

   //调用方法按照最新的数字加载图片
   initImage();
  }else if (code == 40){
   System.out.println("向下");
   if (x==0){
    //表示空白方块已经再最上方了.到达最上方没有图片再能移动了
    return;
   }
   //逻辑:
   //把空白方块上方的数字下移动
   data[x][y]=data[x-1][y];
   data[x-1][y]=0;
   x--;

   //每移动一次,计数器就自增一次.
   step++;

   //调用方法按照最新的数字加载图片
   initImage();
  }else if (code == 65){
   System.out.println("按了A");
   initImage();
  } else if (code==87) {
    //87:W
   data=new int[][]{
           {1,2,3,4},
           {5,6,7,8},
           {9,10,11,12},
           {13,14,15,0}
   };
   initImage();
  }
 }

 //判断data数组中的数据是否跟win数组中相同
 //如果全部相同,返回true,否则返回false
 public Boolean victory(){
  for (int i = 0; i < data.length; i++) {
   //i:依次表示二维数组data里面的索引
   //data[i]:依次表示每一个一维数组
   for (int j = 0; j < data[i].length; j++) {
    if(data[i][j]!=win[i][j]){
     //只要有一个数据不一样,则返回false
     return false;
    }

   }

  }
  //循环结束表示数组遍历比较完毕,全部一样返回true
  return true;
 }

 @Override
 public void actionPerformed(ActionEvent e) {
   //获取当前被点击的条目对象
   Object obj = e.getSource();
   if (obj == replayItem){
    System.out.println("重新游戏");
    //计步器清零
    step=0;
    //再次打乱二维数组中的数据
    initData();
    //重新加载图片
    initImage();
   }else if (obj == reLoginItem){
    System.out.println("重新登录");
    //关闭当前游戏界面
    this.setVisible(false);
    //打开登录界面
    new LoginJFrame();
   }else if (obj == closeItem){
    System.out.println("关闭游戏");
    System.exit(0);
   }else if (obj == accountItem){
    System.out.println("公众号");

    //创建一个弹窗对象
    JDialog jDialog = new JDialog();
    //创建一个管理图片的容器对象JLabel
    JLabel jLabel = new JLabel(new ImageIcon("image\\about.png"));
    //设置位置和宽高
    jLabel.setBounds(0,0,258,258);
    //把图片添加到弹窗当中
    jDialog.getContentPane().add(jLabel);
    //设置弹窗的大小
    jDialog.setSize(344,344);
    //让弹窗置顶
    jDialog.setAlwaysOnTop(true);
    //让弹窗居中
    jDialog.setLocationRelativeTo(null);
    //弹窗关闭则无法操作下面的界面
    jDialog.setModal(true);
    //让弹窗显示出来
    jDialog.setVisible(true);

   }

 }
}
